Design Online Food Delivery Service like Swiggy

Last Updated: December 19, 2025

Ashish

Ashish Pratap Singh

hard

In this chapter, we will explore the low-level design of a simplified food delivery service.

Let's start by clarifying the requirements:

1. Clarifying Requirements

Before starting the design, it's important to ask thoughtful questions to uncover hidden assumptions, clarify ambiguities, and define the system's scope more precisely.

Here is an example of how a conversation between the candidate and the interviewer might unfold:

After gathering the details, we can summarize the key system requirements.

1.1 Functional Requirements

  • Support registration of new users, delivery agents and restaurants.
  • Support adding restaurants and menu items.
  • Allow customers to search for restaurants based on city, menu or location.
  • Allow customers to place orders containing multiple items from a selected restaurant.
  • Notify restaurants of new incoming orders and allow them to update the order status.
  • Auto-assign delivery agents based on availability and proximity
  • Notify relevant parties when the order status changes.
  • Maintain order history for customers.

1.2 Non-Functional Requirements

  • Modularity: The system should be designed with clear separation of components.
  • Extensibility: The design should be flexible enough to support future features.
  • Maintainability: Code should follow object-oriented principles and be easy to test, debug, and evolve.

After the requirements are clear, lets identify the core entities and their responsibilities within the system.

2. Identifying Core Entities

Core entities are the fundamental building blocks of our system. We identify them by analyzing key nouns (e.g., restaurant, user, order, item, delivery agent) and actions (e.g., browse, order, track, update, assign) from the functional requirements. These typically translate directly into classes, enums, or interfaces in an object-oriented design.

Below, we break down the functional requirements and extract the relevant entities. Related requirements are grouped together when they represent the same conceptual unit.

1. Support onboarding and management of restaurants and menu items.

This introduces two key entities:

  • Restaurant: Represents a food provider on the platform. Stores metadata such as name, address, cuisine type, and a reference to its menu.
  • MenuItem: Represents an individual dish offered by a restaurant. Includes attributes like name, description, price, and availability.
  • Menu: Represents a collection of MenuItem objects for a given restaurant.
  • Address: Represents the location of the restaurant, stored in a standardized format for filtering, searching, and delivery logistics.

Restaurants will have a one-to-many relationship with menu items, and each restaurant is associated with a unique menu.

2. Customers should be able to place orders and view their order history.

This introduces:

  • Customer: Represents a platform user who can browse restaurants, place orders, and track their order history.
  • Order: Represents a food order placed by a customer. It includes details such as selected restaurant, delivery address, list of items, and order status.
  • OrderItem: Represents a line item within an order. It references a MenuItem along with quantity and subtotal.

3. The system must support automatic delivery agent assignment.

This introduces:

  • DeliveryAgent: A specialized user who fulfills delivery tasks. Each agent has attributes such as name, availability, current location, and assigned orders.

Assignment of delivery agents can be coordinated based on availability and proximity using a centralized service.

4. Notify relevant parties when the order status changes.

This requires:

  • OrderStatus (enum): Represents the lifecycle state of an order. Possible values include PENDING, ACCEPTED, PREPARING, OUT_FOR_DELIVERY, DELIVERED, and CANCELLED.

Notifications can be sent when the order status transitions, informing the customer, restaurant, and delivery agent.

5. Central orchestration of ordering, assignment, and tracking.

This suggests the need for a core orchestrator:

  • FoodDeliveryService: A high-level service responsible for coordinating the main workflows—placing orders, assigning delivery agents, updating order status, and notifying users.

These core entities define the key abstractions of the Online Food Delivery Service and will guide the structure of your low-level design and class diagrams.

3. Designing Classes and Relationships

This section breaks down the system's architecture into its fundamental classes, their responsibilities, and the relationships that connect them. We also explore the key design patterns that provide robustness and flexibility to the solution.

3.1 Class Definitions

The system is composed of several types of classes, each with a distinct role.

Enums

OrderStatus

Represents the distinct stages in the lifecycle of an order, such as PENDING, PREPARING, OUT_FOR_DELIVERY, and DELIVERED.

OrderStatus

This enables clear state management and triggers for notifications.

Data Classes

Address

A data class holding location information (street, city, coordinates).

Address

It includes a utility method to calculate the distance to another address, which is crucial for proximity-based searches and delivery agent assignment.

MenuItem

Represents a single food item available at a restaurant, containing its ID, name, price, and availability.

Acts as a container for a collection of MenuItem objects, representing a restaurant's full menu.

OrderItem

OrderItem

A linking class that connects a MenuItem with a specific quantity for an Order.

Core Classes

User (Abstract Class)

A base class for all human actors in the system (Customer, DeliveryAgent).

User

Holds common properties like ID, name, and phone number. It also implements OrderObserver.

  • Customer: Represents the end-user placing an order. It holds personal details, address information, and a history of their orders. It acts as a concrete Observer.
  • DeliveryAgent: Represents the person responsible for delivering the order. It maintains their current location and availability status (isAvailable). It also acts as a concrete Observer.

Restaurant

Represents a food establishment.

Restaurant

It contains its address, a Menu of items it offers, and also acts as a concrete Observer to track the status of orders placed with it.

Order

The central and most critical class in the system.

Order

It encapsulates all details of a single transaction: the Customer, Restaurant, OrderItems, and assigned DeliveryAgent. It acts as the Subject in the Observer pattern, maintaining a list of observers and notifying them whenever its status changes.

FoodDeliveryService (Singleton & Facade)

The main entry point for all client interactions.

FoodDeliveryService

It manages all the core entities (customers, restaurants, agents, orders) and orchestrates the entire workflow from searching and placing an order to assigning a delivery agent. It provides a simple, unified API to the complex underlying system.

3.2 Class Relationships

The relationships between classes define the system's structure and data flow.

Composition

  • FoodDeliveryService has collections of Customer, Restaurant, DeliveryAgent, and Order. These entities are managed within and have their lifecycle controlled by the service.
  • A Restaurant has a Menu.
  • A Menu has a collection of MenuItems.
  • An Order is composed of a list of OrderItems.

Association

  • An Order is associated with one Customer, one Restaurant, and one DeliveryAgent.
  • FoodDeliveryService is associated with a DeliveryAssignmentStrategy to decide how to assign agents.
  • FoodDeliveryService uses one or more RestaurantSearchStrategy objects to filter restaurants.
  • An Order (Subject) is associated with multiple OrderObservers.

Inheritance

  • Customer and DeliveryAgent are specialized types of User and inherit from it.
  • The concrete strategy classes (NearestAvailableAgentStrategy, SearchByCityStrategy, etc.) implement their respective strategy interfaces.

Dependency

  • The FoodDeliveryService depends on the strategy interfaces to perform its core functions of searching and assignment.
  • The Order class depends on the OrderObserver interface to notify participants.
  • The client (FoodDeliveryServiceDemo) depends on the FoodDeliveryService facade to interact with the system.

3.3 Key Design Patterns

Facade Pattern

The FoodDeliveryService class serves as a facade. It provides a simple, high-level API (placeOrder, searchRestaurants, updateOrderStatus) that hides the complex internal interactions between orders, users, strategies, and notifications.

Singleton Pattern

FoodDeliveryService is implemented as a singleton to ensure there is only one instance coordinating the entire system. This provides a single, global point of access and prevents state inconsistencies.

Strategy Pattern

This pattern is used extensively to provide flexibility for core business logic.

Restaurant Searching

RestaurantSearchStrategy

RestaurantSearchStrategy allows the system to use different algorithms (by city, proximity, menu keyword) to filter restaurants without changing the FoodDeliveryService class. These strategies can even be chained together.

Delivery Assignment

DeliveryAssignmentStrategy

DeliveryAssignmentStrategy allows the logic for assigning delivery agents to be swapped out easily.

Observer Pattern

This pattern is crucial for real-time notifications. The Order object is the Subject, and the Customer, Restaurant, and DeliveryAgent are Observers.

OrderObserver

When the order's status changes (e.g., from PREPARING to READY_FOR_PICKUP), the Order automatically notifies all its registered observers, keeping them in sync.

3.4 Full Class Diagram

Food Delivery Service

4. Implementation

4.1 OrderStatus (Enum)

Defines the stages of an order’s lifecycle, enabling status transitions, validations, and notification triggers.

1class OrderStatus(Enum):
2    PENDING = "PENDING"
3    CONFIRMED = "CONFIRMED"
4    PREPARING = "PREPARING"
5    READY_FOR_PICKUP = "READY_FOR_PICKUP"
6    OUT_FOR_DELIVERY = "OUT_FOR_DELIVERY"
7    DELIVERED = "DELIVERED"
8    CANCELLED = "CANCELLED"

4.2 Address

Represents the physical location of users, restaurants, and delivery agents.

1class Address:
2    def __init__(self, street: str, city: str, zip_code: str, latitude: float, longitude: float):
3        self.street = street
4        self.city = city
5        self.zip_code = zip_code
6        self.latitude = latitude
7        self.longitude = longitude
8
9    def get_city(self) -> str:
10        return self.city
11
12    def distance_to(self, other: 'Address') -> float:
13        lat_diff = self.latitude - other.latitude
14        lon_diff = self.longitude - other.longitude
15        return math.sqrt(lat_diff * lat_diff + lon_diff * lon_diff)
16
17    def __str__(self) -> str:
18        return f"{self.street}, {self.city}, {self.zip_code} @({self.latitude}, {self.longitude})"

Distance computation is used for proximity-based search and agent assignment.

4.3 OrderObserver

Abstract contract for all order participants (Customer, Restaurant, DeliveryAgent) to receive live order updates.

1class OrderObserver(ABC):
2    @abstractmethod
3    def on_update(self, order: 'Order'):
4        pass

4.4 User

1class User(OrderObserver):
2    def __init__(self, name: str, phone: str):
3        self.id = str(uuid.uuid4())
4        self.name = name
5        self.phone = phone
6
7    def get_id(self) -> str:
8        return self.id
9
10    def get_name(self) -> str:
11        return self.name

4.5 Customer

1class Customer(User):
2    def __init__(self, name: str, phone: str, address: Address):
3        super().__init__(name, phone)
4        self.address = address
5        self.order_history: List['Order'] = []
6
7    def add_order_to_history(self, order: 'Order'):
8        self.order_history.append(order)
9
10    def get_address(self) -> Address:
11        return self.address
12
13    def on_update(self, order: 'Order'):
14        print(f"--- Notification for Customer {self.get_name()} ---")
15        print(f"  Order {order.get_id()} is now {order.get_status().value}.")
16        print("-------------------------------------\n")

4.6 DeliveryAgent

1class DeliveryAgent(User):
2    def __init__(self, name: str, phone: str, current_location: Address):
3        super().__init__(name, phone)
4        self.is_available = True
5        self.current_location = current_location
6        self._lock = threading.Lock()
7
8    def set_available(self, available: bool):
9        with self._lock:
10            self.is_available = available
11
12    def is_available_agent(self) -> bool:
13        with self._lock:
14            return self.is_available
15
16    def set_current_location(self, current_location: Address):
17        self.current_location = current_location
18
19    def get_current_location(self) -> Address:
20        return self.current_location
21
22    def on_update(self, order: 'Order'):
23        print(f"--- Notification for Delivery Agent {self.get_name()} ---")
24        print(f"  Order {order.get_id()} update: Status is {order.get_status().value}.")
25        print("-------------------------------------------\n")

4.7 MenuItem

1class MenuItem:
2    def __init__(self, item_id: str, name: str, price: float):
3        self.id = item_id
4        self.name = name
5        self.price = price
6        self.available = True
7
8    def get_id(self) -> str:
9        return self.id
10
11    def set_available(self, available: bool):
12        self.available = available
13
14    def get_name(self) -> str:
15        return self.name
16
17    def get_price(self) -> float:
18        return self.price
19
20    def get_menu_item(self) -> str:
21        return f"Name: {self.name}, Price: {self.price}"

4.8 Menu

1class Menu:
2    def __init__(self):
3        self.items: Dict[str, MenuItem] = {}
4
5    def add_item(self, item: MenuItem):
6        self.items[item.get_id()] = item
7
8    def get_item(self, item_id: str) -> MenuItem:
9        return self.items.get(item_id)
10
11    def get_items(self) -> Dict[str, MenuItem]:
12        return self.items

4.9 Restaurant

1class Restaurant(OrderObserver):
2    def __init__(self, name: str, address: Address):
3        self.id = str(uuid.uuid4())
4        self.name = name
5        self.address = address
6        self.menu = Menu()
7
8    def get_id(self) -> str:
9        return self.id
10
11    def get_name(self) -> str:
12        return self.name
13
14    def get_address(self) -> Address:
15        return self.address
16
17    def get_menu(self) -> Menu:
18        return self.menu
19
20    def add_to_menu(self, item: MenuItem):
21        self.menu.add_item(item)
22
23    def on_update(self, order: 'Order'):
24        print(f"--- Notification for Restaurant {self.name} ---")
25        print(f"  Order {order.get_id()} has been updated to {order.get_status().value}.")
26        print("----------------------------------------\n")

4.9 OrderItem

1class OrderItem:
2    def __init__(self, item: MenuItem, quantity: int):
3        self.item = item
4        self.quantity = quantity
5
6    def get_item(self) -> MenuItem:
7        return self.item
8
9    def get_quantity(self) -> int:
10        return self.quantity

4.10 Order

1class Order:
2    def __init__(self, customer: Customer, restaurant: Restaurant, items: List[OrderItem]):
3        self.id = str(uuid.uuid4())
4        self.customer = customer
5        self.restaurant = restaurant
6        self.items = items
7        self.status = OrderStatus.PENDING
8        self.delivery_agent: Optional[DeliveryAgent] = None
9        self.observers: List[OrderObserver] = []
10        self.add_observer(customer)
11        self.add_observer(restaurant)
12
13    def add_observer(self, observer: OrderObserver):
14        self.observers.append(observer)
15
16    def notify_observers(self):
17        for observer in self.observers:
18            observer.on_update(self)
19
20    def set_status(self, new_status: OrderStatus):
21        if self.status != new_status:
22            self.status = new_status
23            self.notify_observers()
24
25    def cancel(self) -> bool:
26        if self.status == OrderStatus.PENDING:
27            self.set_status(OrderStatus.CANCELLED)
28            return True
29        return False
30
31    def assign_delivery_agent(self, agent: DeliveryAgent):
32        self.delivery_agent = agent
33        self.add_observer(agent)
34        agent.set_available(False)
35
36    def get_id(self) -> str:
37        return self.id
38
39    def get_status(self) -> OrderStatus:
40        return self.status
41
42    def get_customer(self) -> Customer:
43        return self.customer
44
45    def get_restaurant(self) -> Restaurant:
46        return self.restaurant
47
48    def get_delivery_agent(self) -> Optional[DeliveryAgent]:
49        return self.delivery_agent

4.11 DeliveryAssignmentStrategy

1class DeliveryAssignmentStrategy(ABC):
2    @abstractmethod
3    def find_agent(self, order: Order, agents: List[DeliveryAgent]) -> Optional[DeliveryAgent]:
4        pass
5
6class NearestAvailableAgentStrategy(DeliveryAssignmentStrategy):
7    def find_agent(self, order: Order, available_agents: List[DeliveryAgent]) -> Optional[DeliveryAgent]:
8        restaurant_address = order.get_restaurant().get_address()
9        customer_address = order.get_customer().get_address()
10
11        available_agents_filtered = [agent for agent in available_agents if agent.is_available_agent()]
12        
13        if not available_agents_filtered:
14            return None
15
16        min_distance = float('inf')
17        best_agent = None
18
19        for agent in available_agents_filtered:
20            total_distance = self.calculate_total_distance(agent, restaurant_address, customer_address)
21            if total_distance < min_distance:
22                min_distance = total_distance
23                best_agent = agent
24
25        return best_agent
26
27    def calculate_total_distance(self, agent: DeliveryAgent, restaurant_address: Address, customer_address: Address) -> float:
28        agent_to_restaurant_dist = agent.get_current_location().distance_to(restaurant_address)
29        restaurant_to_customer_dist = restaurant_address.distance_to(customer_address)
30        return agent_to_restaurant_dist + restaurant_to_customer_dist

4.12 RestaurantSearchStrategy

The system's core business logic—how to search for restaurants and how to assign a delivery agent—can have many variations. The Strategy pattern makes these algorithms interchangeable.

1class RestaurantSearchStrategy(ABC):
2    @abstractmethod
3    def filter(self, all_restaurants: List[Restaurant]) -> List[Restaurant]:
4        pass
5
6class SearchByCityStrategy(RestaurantSearchStrategy):
7    def __init__(self, city: str):
8        self.city = city
9
10    def filter(self, all_restaurants: List[Restaurant]) -> List[Restaurant]:
11        return [r for r in all_restaurants if r.get_address().get_city().lower() == self.city.lower()]
12
13class SearchByMenuKeywordStrategy(RestaurantSearchStrategy):
14    def __init__(self, keyword: str):
15        self.keyword = keyword.lower()
16
17    def filter(self, all_restaurants: List[Restaurant]) -> List[Restaurant]:
18        result = []
19        for r in all_restaurants:
20            for item in r.get_menu().get_items().values():
21                if self.keyword in item.get_name().lower():
22                    result.append(r)
23                    break
24        return result
25
26class SearchByProximityStrategy(RestaurantSearchStrategy):
27    def __init__(self, user_location: Address, max_distance: float):
28        self.user_location = user_location
29        self.max_distance = max_distance
30
31    def filter(self, all_restaurants: List[Restaurant]) -> List[Restaurant]:
32        filtered = [r for r in all_restaurants if self.user_location.distance_to(r.get_address()) <= self.max_distance]
33        filtered.sort(key=lambda r: self.user_location.distance_to(r.get_address()))
34        return filtered
  • Each strategy class encapsulates a specific algorithm. For example, SearchByProximityStrategy contains the logic for filtering and sorting restaurants by distance.

4.13 FoodDeliveryService

This class is a Singleton that provides a simplified, high-level API to the entire complex subsystem.

1class FoodDeliveryService:
2    _instance = None
3    _lock = threading.Lock()
4
5    def __init__(self):
6        if FoodDeliveryService._instance is not None:
7            raise Exception("This class is a singleton!")
8        self.customers: Dict[str, Customer] = {}
9        self.restaurants: Dict[str, Restaurant] = {}
10        self.delivery_agents: Dict[str, DeliveryAgent] = {}
11        self.orders: Dict[str, Order] = {}
12        self.assignment_strategy: Optional[DeliveryAssignmentStrategy] = None
13
14    @staticmethod
15    def get_instance():
16        if FoodDeliveryService._instance is None:
17            with FoodDeliveryService._lock:
18                if FoodDeliveryService._instance is None:
19                    FoodDeliveryService._instance = FoodDeliveryService()
20        return FoodDeliveryService._instance
21
22    def set_assignment_strategy(self, assignment_strategy: DeliveryAssignmentStrategy):
23        self.assignment_strategy = assignment_strategy
24
25    def register_customer(self, name: str, phone: str, address: Address) -> Customer:
26        customer = Customer(name, phone, address)
27        self.customers[customer.get_id()] = customer
28        return customer
29
30    def register_restaurant(self, name: str, address: Address) -> Restaurant:
31        restaurant = Restaurant(name, address)
32        self.restaurants[restaurant.get_id()] = restaurant
33        return restaurant
34
35    def register_delivery_agent(self, name: str, phone: str, initial_location: Address) -> DeliveryAgent:
36        delivery_agent = DeliveryAgent(name, phone, initial_location)
37        self.delivery_agents[delivery_agent.get_id()] = delivery_agent
38        return delivery_agent
39
40    def place_order(self, customer_id: str, restaurant_id: str, items: List[OrderItem]) -> Order:
41        customer = self.customers.get(customer_id)
42        restaurant = self.restaurants.get(restaurant_id)
43        if customer is None or restaurant is None:
44            raise KeyError("Customer or Restaurant not found.")
45
46        order = Order(customer, restaurant, items)
47        self.orders[order.get_id()] = order
48        customer.add_order_to_history(order)
49        print(f"Order {order.get_id()} placed by {customer.get_name()} at {restaurant.get_name()}.")
50        order.set_status(OrderStatus.PENDING)
51        return order
52
53    def update_order_status(self, order_id: str, new_status: OrderStatus):
54        order = self.orders.get(order_id)
55        if order is None:
56            raise KeyError("Order not found.")
57
58        order.set_status(new_status)
59
60        if new_status == OrderStatus.READY_FOR_PICKUP:
61            self.assign_delivery(order)
62
63    def cancel_order(self, order_id: str):
64        order = self.orders.get(order_id)
65        if order is None:
66            print(f"ERROR: Order with ID {order_id} not found.")
67            return
68
69        if order.cancel():
70            print(f"SUCCESS: Order {order_id} has been successfully canceled.")
71        else:
72            print(f"FAILED: Order {order_id} could not be canceled. Its status is: {order.get_status().value}")
73
74    def assign_delivery(self, order: Order):
75        available_agents = list(self.delivery_agents.values())
76
77        best_agent = self.assignment_strategy.find_agent(order, available_agents)
78        if best_agent:
79            order.assign_delivery_agent(best_agent)
80            distance = best_agent.get_current_location().distance_to(order.get_restaurant().get_address())
81            print(f"Agent {best_agent.get_name()} (dist: {distance:.2f}) assigned to order {order.get_id()}.")
82            order.set_status(OrderStatus.OUT_FOR_DELIVERY)
83        else:
84            print(f"No available delivery agents found for order {order.get_id()}")
85
86    def search_restaurants(self, strategies: List[RestaurantSearchStrategy]) -> List[Restaurant]:
87        results = list(self.restaurants.values())
88
89        for strategy in strategies:
90            results = strategy.filter(results)
91
92        return results
93
94    def get_restaurant_menu(self, restaurant_id: str) -> Menu:
95        restaurant = self.restaurants.get(restaurant_id)
96        if restaurant is None:
97            raise KeyError(f"Restaurant with ID {restaurant_id} not found.")
98        return restaurant.get_menu()
  • Facade Pattern: The facade provides simple methods like placeOrder and searchRestaurants, hiding the complex interactions between orders, observers, and strategies.

4.14 FoodDeliveryServiceDemo

The demo class validates the end-to-end functionality by simulating a customer's journey from searching to receiving an order.

1class FoodDeliveryServiceDemo:
2    @staticmethod
3    def main():
4        # 1. Setup the system
5        service = FoodDeliveryService.get_instance()
6        service.set_assignment_strategy(NearestAvailableAgentStrategy())
7
8        # 2. Define Addresses
9        alice_address = Address("123 Maple St", "Springfield", "12345", 40.7128, -74.0060)
10        pizza_address = Address("456 Oak Ave", "Springfield", "12345", 40.7138, -74.0070)
11        burger_address = Address("789 Pine Ln", "Springfield", "12345", 40.7108, -74.0050)
12        taco_address = Address("101 Elm Ct", "Shelbyville", "54321", 41.7528, -75.0160)
13
14        # 3. Register entities
15        alice = service.register_customer("Alice", "123-4567-890", alice_address)
16        pizza_palace = service.register_restaurant("Pizza Palace", pizza_address)
17        burger_barn = service.register_restaurant("Burger Barn", burger_address)
18        taco_town = service.register_restaurant("Taco Town", taco_address)
19        service.register_delivery_agent("Bob", "321-4567-880", Address("1 B", "Springfield", "12345", 40.71, -74.00))
20
21        # 4. Setup menus
22        pizza_palace.add_to_menu(MenuItem("P001", "Margherita Pizza", 12.99))
23        pizza_palace.add_to_menu(MenuItem("P002", "Veggie Pizza", 11.99))
24        burger_barn.add_to_menu(MenuItem("B001", "Classic Burger", 8.99))
25        taco_town.add_to_menu(MenuItem("T001", "Crunchy Taco", 3.50))
26
27        # 5. Demonstrate Search Functionality
28        print("\n--- 1. Searching for Restaurants ---")
29
30        # (A) Search by City
31        print("\n(A) Restaurants in 'Springfield':")
32        city_search = [SearchByCityStrategy("Springfield")]
33        springfield_restaurants = service.search_restaurants(city_search)
34        for r in springfield_restaurants:
35            print(f"  - {r.get_name()}")
36
37        # (B) Search for restaurants near Alice
38        print("\n(B) Restaurants near Alice (within 0.01 distance units):")
39        proximity_search = [SearchByProximityStrategy(alice_address, 0.01)]
40        nearby_restaurants = service.search_restaurants(proximity_search)
41        for r in nearby_restaurants:
42            distance = alice_address.distance_to(r.get_address())
43            print(f"  - {r.get_name()} (Distance: {distance:.4f})")
44
45        # (C) Search for restaurants that serve 'Pizza'
46        print("\n(C) Restaurants that serve 'Pizza':")
47        menu_search = [SearchByMenuKeywordStrategy("Pizza")]
48        pizza_restaurants = service.search_restaurants(menu_search)
49        for r in pizza_restaurants:
50            print(f"  - {r.get_name()}")
51
52        # (D) Combined Search: Find restaurants near Alice that serve 'Burger'
53        print("\n(D) Burger joints near Alice:")
54        combined_search = [
55            SearchByProximityStrategy(alice_address, 0.01),
56            SearchByMenuKeywordStrategy("Burger")
57        ]
58        burger_joints_near_alice = service.search_restaurants(combined_search)
59        for r in burger_joints_near_alice:
60            print(f"  - {r.get_name()}")
61
62        # 6. Demonstrate Browsing a Menu
63        print("\n--- 2. Browsing a Menu ---")
64        print("\nMenu for 'Pizza Palace':")
65        pizza_menu = service.get_restaurant_menu(pizza_palace.get_id())
66        for item in pizza_menu.get_items().values():
67            print(f"  - {item.get_name()}: ${item.get_price():.2f}")
68
69        # 7. Alice places an order from a searched restaurant
70        print("\n--- 3. Placing an Order ---")
71        if pizza_restaurants:
72            chosen_restaurant = pizza_restaurants[0]
73            chosen_item = chosen_restaurant.get_menu().get_item("P001")
74
75            print(f"\nAlice is ordering '{chosen_item.get_name()}' from '{chosen_restaurant.get_name()}'.")
76            order = service.place_order(alice.get_id(), chosen_restaurant.get_id(), [OrderItem(chosen_item, 1)])
77
78            print("\n--- Restaurant starts preparing the order ---")
79            service.update_order_status(order.get_id(), OrderStatus.PREPARING)
80
81            print("\n--- Order is ready for pickup ---")
82            print("System will now find the nearest available delivery agent...")
83            service.update_order_status(order.get_id(), OrderStatus.READY_FOR_PICKUP)
84
85            print("\n--- Agent delivers the order ---")
86            service.update_order_status(order.get_id(), OrderStatus.DELIVERED)
87
88
89if __name__ == "__main__":
90    FoodDeliveryServiceDemo.main()

5. Run and Test

Files19
entities
enum
observers
strategies
food_delivery_service_demo.py
main
food_delivery_service.py
food_delivery_service_demo.pymain
Output

6. Quiz

Design Online Food Delivery Service Quiz

1 / 19
Multiple Choice

Which entity should maintain the collection of offered dishes for each restaurant in an online food delivery platform?

How helpful was this article?

Comments


0/2000

No comments yet. Be the first to comment!

Copilot extension content script